﻿
#include "config.h"
#include "Manager.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

#define PARTING_LINE(c)     cout << "\t" << setfill((c)) << setw(60) << (c) << endl << setfill(' ')
#define ORIGIN_ID           100000000

//////////////////////////////////////////////////////////////////////////
struct SorterByID {
    bool operator()(const Student * next, const Student * prev) {
        return next->id_ > prev->id_ ? true : false;
    }
};

struct SorterByName {
    bool operator()(const Student * next, const Student * prev) {
        return next->name_ > prev->name_ ? true : false;
    }
};

struct SorterByChinese {
    bool operator()(const Student * next, const Student * prev) {
        return next->scores_.zh_ > prev->scores_.zh_ ? true : false;
    }
};

struct SearcherByID {
    SearcherByID(unsigned long id) : id_(id) {}
    bool operator()(const Student* s) {
        return s->id_ == id_;
    }
    unsigned long id_;
};

struct SearcherByName {
    SearcherByName(const string& name) : name_(name) {}
    bool operator()(const Student* s) {
        return s->name_ == name_;
    }
    string name_;
};

//////////////////////////////////////////////////////////////////////////
Manager::Manager()
{
    InitUniqID();
}

Manager::~Manager()
{
    ClearList(ls_);
    SaveUniqID();
}

int Manager::MainMenu()
{
    system(SYSTEM_CMD_CLEAR);

    cout << "\n\t\t\t欢迎使用学生成绩管理系统-" << PROJECT_VERSION << endl;
    PARTING_LINE('*');
    cout << "\t" << setiosflags(ios::left) << setw(30) << "1----添 加 学 员." << resetiosflags(ios::left)
        << setiosflags(ios::right) << setw(30) << "2----删 除 学 员." << resetiosflags(ios::right) << endl
        << "\t" << setiosflags(ios::left) << setw(30) << "3----修 改 学 员." << resetiosflags(ios::left)
        << setiosflags(ios::right) << setw(30) << "4----查 询 学 员." << resetiosflags(ios::right) << endl
        << "\t" << setiosflags(ios::left) << setw(30) << "5----显 示 学 员." << resetiosflags(ios::left)
        << setiosflags(ios::right) << setw(30) << "6----排 序 学 员." << resetiosflags(ios::right) << endl
        << "\t" << setiosflags(ios::left) << setw(30) << "7----导 入/导 出." << resetiosflags(ios::left)
        << setiosflags(ios::right) << setw(30) << "0----退 出 系 统." << resetiosflags(ios::right) << endl;
    PARTING_LINE('*');

    int choice;
    while (choice = GetChoice("请选择："))
    {
        if (choice >= 0 && choice <= 7)
            break;
    }
    return choice;
}

void Manager::Add()
{
    while (1)
    {
        Student* s = new Student;
        cout << "请输入学员姓名（string） 性别（string） 语文成绩（float） 数学成绩（float） 英语成绩（float）：" << endl;
        cin >> *s;
        if (cin.fail())
        {
            cout << "输入数据不符合规范！" << endl;
            cin.clear();
            delete s;
        }
        else
        {
            s->id_ = ++uniqid_;
            ls_.push_back(s);
        }
        cin.ignore(100, '\n');

        cout << "是否继续添加？（y / [n]）：";
        string choice;
        getline(cin, choice);
        if (choice.empty() || choice != "y")
        {
            break;
        }
    }
}

void Manager::Delete()
{
    cout << "待续..." << endl;
    BreakConsole();
}

void Manager::Modify()
{
    cout << "待续..." << endl;
    BreakConsole();
}

void Manager::Search()
{
    system(SYSTEM_CMD_CLEAR);

    cout << "\t查找学员" << endl;
    PARTING_LINE('*');
    cout << setiosflags(ios::left)
        << "\t" <<  setw(20) << "1--按 学 号."
        << setw(20) << "2--按 姓 名."
        << setw(20) << "0--返 回." << endl
        << resetiosflags(ios::left);
    PARTING_LINE('*');

    int choice;
    while (choice = GetChoice("请选择："))
    {
        if (choice == 1)
        {
            cout << "请输入学号：";
            unsigned long no;
            cin >> no;
            if (cin.fail())
            {
                cout << "输入数据不符合规范！" << endl;
                cin.clear();
                cin.ignore(100, '\n');
                continue;
            }
            else
            {
                list<Student*> result;
                list<Student*>::iterator it = ls_.begin();
                while (1) {
                    it = find_if(it, ls_.end(), SearcherByID(no));
                    if (it == ls_.end())
                        break;

                    result.push_back(*it);
                    it++;
                }

                Show(result);

                cin.ignore(100, '\n');
            }
        }
        else if (choice == 2)
        {
            cout << "请输入姓名：";
            string name;
            cin >> name;

            list<Student*> result;
            list<Student*>::iterator it = ls_.begin();
            while (1) {
                it = find_if(it, ls_.end(), SearcherByName(name));
                if (it == ls_.end())
                    break;

                result.push_back(*it);
                it++;
            }

            Show(result);

            cin.ignore(100, '\n');
        }
    }
}

void Manager::Sort()
{
    system(SYSTEM_CMD_CLEAR);

    cout << "\t学员排序" << endl;
    PARTING_LINE('*');
    cout << setiosflags(ios::left)
        << "\t" << setw(30) << "1----按 学 号." << setw(30) << "2----按 姓 名." << endl
        << "\t" << setw(30) << "3----按 语 文 成 绩." << setw(30) << "0--返 回." << endl
        << resetiosflags(ios::left);
    PARTING_LINE('*');

    int choice;
    while (choice = GetChoice("请选择："))
    {
        if (choice == 1)
        {
            ls_.sort(SorterByID());
        }
        else if (choice == 2)
        {
            ls_.sort(SorterByName());
        }
        else if (choice == 3)
        {
            ls_.sort(SorterByChinese());
        }
    }
}

void Manager::ImportAndExport()
{
    system(SYSTEM_CMD_CLEAR);

    cout << "\t导入/导出" << endl;
    PARTING_LINE('*');
    cout << setiosflags(ios::left)
        << "\t" << setw(20) << "1--读 取 文 件."
        << setw(20) << "2--写 入 文 件."
        << setw(20) << "0--返 回." << endl
        << resetiosflags(ios::left);
    if (ls_.size() > 0) {
        PARTING_LINE('~');
        cout << "\t" << setiosflags(ios::left) << setw(60)
            << "注意：当前记录不为空，载入文件会覆盖当前记录！！" << endl
            << resetiosflags(ios::left);
    }
    PARTING_LINE('*');

    int choice;
    while (choice = GetChoice("请选择：")) {
        if (choice == 1)
        {
            ifstream ifs("record.dat");
            if (ifs.is_open())
            {
                ClearList(ls_);

                while (!ifs.eof())
                {
                    Student* s = new Student;
                    ifs >> *s;
                    if (ifs.fail())
                    {
                        delete s;
                    }
                    else
                    {
                        if (s->id_ > uniqid_)
                            uniqid_ = s->id_;

                        ls_.push_back(s);
                    }
                }
                ifs.close();
            }
            else
            {
                cout << "读取文件失败！" << endl;
            }
        }
        else if (choice == 2)
        {
            if (ls_.size() > 0)
            {
                ofstream ofs("record.dat");
                if (ofs.is_open())
                {
                    list<Student*>::const_iterator it = ls_.begin();
                    for (; it != ls_.end(); ++it)
                    {
                        ofs << **it << endl;
                    }
                    ofs.close();
                }
            }
        }
    }
}

void Manager::Show()
{
    Show(ls_);
    BreakConsole();
}

bool Manager::Exit()
{
    if (ls_.size() > 0)
    {
        cout << "当前记录不为空，此操作可能会导致数据丢失，是否继续退出？（[y] / n）：";

        string choice;
        getline(cin, choice);
        if (choice == "n")
        {
            return false;
        }
    }

    return true;
}

void Manager::InitUniqID()
{
    ifstream idfile("id.txt");
    if (idfile.is_open())
    {
        idfile >> uniqid_;
        if (idfile.fail())
        {
            uniqid_ = ORIGIN_ID;
        }
    }
    else
    {
        uniqid_ = ORIGIN_ID;
    }
}

bool Manager::SaveUniqID()
{
    ofstream idfile("id.txt");
    if (idfile.is_open())
    {
        idfile << uniqid_;
        if (idfile.fail())
            return false;
    }

    return true;
}

void Manager::ClearList(list<Student*>& ls)
{
    list<Student*>::iterator it = ls_.begin();
    for (; it != ls_.end(); ++it)
    {
        delete *it;
    }
    ls_.clear();
}

int Manager::GetChoice(const string& prompt)
{
    int choice;
    while (1)
    {
        cout << prompt;
        string s;
        getline(cin, s);
        if (s.empty())
        {
            cout << "\r";
            continue;
        }
        else if (s.length() > 1)
        {
            continue;
        }
        else
        {
            choice = s.at(0) - '0';
            if (choice >= 0 && choice <= 9)
                break;
            else
                continue;
        }
    }
    return choice;
}

void Manager::Show(const list<Student*> ls)
{
    setiosflags(ios::left);
    cout << "\t" << setw(6) << "序号"
        << setw(12) << "学号"
        << setw(10) << "姓名"
        << setw(8) << "性别"
        << setw(8) << "语文"
        << setw(8) << "数学"
        << setw(8) << "英语" << endl;
    PARTING_LINE('-');

    list<Student*>::const_iterator it = ls.begin();
    for (int index = 1; it != ls.end(); ++it, index++)
    {
        cout << "\t" << setw(6) << index << **it << endl;
    }

    resetiosflags(ios::left);
}

void Manager::BreakConsole()
{
    cout << "Press any key to continue...";
    cin.get();
}

